
const { $fn } = window

export const toCamelCase = str => {
	str = str?.replace(/[-_\s]+(.)?/g, (match, g) => g ? g.toUpperCase() : '')
	return str ? str[0].toUpperCase() + str.substr(1) : ''
}

export const keyData = {
	'PRI': '.primary_key()',
	'UNI': '.unique_key()',
}
let int = {
	'integer'			: 'integer()',
	'int'				: 'integer()',
	'int unsigned' 		: 'unsigned()',
	'tinyint'			: 'tiny_integer()',
	'tinyint unsigned'	: 'tiny_unsigned()',
	'smallint'			: 'small_integer()',
	'smallint unsigned'	: 'small_unsigned()',
	'bigint'			: 'big_integer()',
	'bigint unsigned'	: 'big_unsigned()',
	'float'				: 'float()',
	'double'			: 'double()',
	'decimal(10,0)'		: 'decimal()',
	'decimal'			: 'decimal_len(x,y)',
}
let date = {
	'timestamp'			: 'timestamp()',
	'date_time'			: 'date_time()',
	'date'				: 'date()',
	'year'				: 'year(Some( x ))',
}
let boolean = {
	'bool'				: 'boolean()',
	'boolean'			: 'boolean()',
}
const typeObj = {
	...int,
	'char(1)' 			: 'char()',
	'char' 				: 'char_len(x)',
	'varchar(255)' 		: 'string()',
	'varchar' 			: 'string_len(x)',
	'text' 				: 'text()',
	
	...boolean,
	
	...date,
	
	'blob'				: 'binary()',
	'binary'			: 'binary_len(x)',
	'tinyblob'			: 'blob( BlobSize::Tiny )',
	'mediumblob'		: 'blob( BlobSize::Medium  )',
	'longblob'			: 'blob( BlobSize::Long )',
	'binary(16)'		: 'uuid()',
	'bit'				: 'bit( Some(x) )',
	
	'json'				: 'json()',
}
const reg = /\([\d\s,]+\)/g

export const createMigration = ({ data, table_name, template, table_comment }) => {
	let back_name = ''
	let back_col = ''
	table_name = toCamelCase( table_name )
	let pkey = []
	data.forEach(({ Field, Type, Null, Key, Default, Extra, Comment }, i) => {
		let col_name = toCamelCase( Field )
		back_name +=  col_name +  (( i === data.length - 1 ) ? '\t' : ',\n\t')
		let auto_increment = ''
		if( Default?.includes?.('CURRENT_TIMESTAMP') ){
			Default = 'Expr::current_timestamp()'
		}
		if( Key === 'PRI' ){
			pkey.push(col_name)
		}
		if( Extra ) {
			if( Extra.includes?.('DEFAULT_GENERATED') ) {
				Extra = Extra.replace('DEFAULT_GENERATED','').trim()
			}
			Extra = Extra.toLowerCase()
			if( Extra === 'auto_increment' ){
				auto_increment = '.auto_increment()'
				Extra = ''
			}
			
		}
		if( reg.test(Type) && Type !== 'char(1)' && Type !== 'varchar(255)' && Type !== 'decimal(10,0)'){
			let x = null
			let y = null
			let type = Type.replace(reg, '') // varchar
			let m = Type.match( reg )
			if( $fn.hasArray(m) ){
				let s = m[0]
				s = s.replace('(','')
				s = s.replace(')','')
				s = s.split(',')
				x = +s[0]
				y = +s?.[1]
			}
			Type = typeObj[type]
			if( x ){
				Type = Type.replace('x',x)
			}
			if( y ){
				Type = Type.replace('y',y)
			}
		}else{
			Type = typeObj[Type]
		}

let back_col_temp = `
.col( ColumnDef::new(${ table_name }::${ col_name })
${ '.' + Type }
${ Null === 'NO' ? '.not_null()' : '' }
${ auto_increment }
${ $fn.isNotEmpty(Key) ? keyData[Key] : '' }
${ $fn.isNotEmpty(Default) ? '.default(' + Default + ')' : '' }
${ $fn.isNotEmpty(Extra)  ? '.extra("' + Extra + '")' : '' }
${ $fn.isNotEmpty(Comment)  ? '.comment("' + Comment + '")' : '' }
 )`

		back_col += back_col_temp.replace(/\n/g,'')  + (( i === data.length - 1 ) ? '\t\t\t\t' : '\n\t\t\t\t')
	})
	if( pkey.length > 1 ){
		back_col = back_col.replace('primary_key()', '')
		let str = ''
		pkey.forEach(v=>{
			str += `.col(${table_name}::${v})`
		})
		str = `.primary_key(Index::create()${str})` + '\n\t\t\t\t'
		back_col = str + back_col
	}
	// 表模板
	template = template.replace(/%table_name%/g, table_name)
	template = template.replace(/%table_comment%/g, table_comment ? `.comment("${table_comment}")` : '')
	template = template.replace(/%#%/g, back_col)
	template = template.replace(/%\$%/g, back_name)
	
	return template
}

export const getBackData = ({ cols, is_tab }) => {
	let column = ''
	let model = ''
	let column_arr = []
	let model_arr = []
	let tab = is_tab ? '\t\t' : ''
	cols.forEach(({ Field, Type, Null })=>{
		let name = Field
		let data_type = Type
		let not_null = Null === 'NO'
		if( !['create_user', 'update_user', 'create_time', 'update_time'].includes(name) ) {
			let col_name = toCamelCase(name)
			column_arr.push( 'Column::'+ col_name )
			if( name === 'id' ) return
			// model
			let m = null
			if( data_type.includes('char') || data_type.includes('text') ){
				m = `${name} : Set( query::str${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type.includes('blob') || data_type.includes('binary')){
				m = `${name} : Set( query::blob${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type === 'int' || data_type === 'integer'){
				m = `${name} : Set( query::i32${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type === 'int unsigned' || data_type === 'integer unsigned'){
				m = `${name} : Set( query::u32${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type === 'tinyint' || data_type === 'boolean' || data_type =='bool'){
				m = `${name} : Set( query::i8${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type === 'tinyint unsigned()'){
				m = `${name} : Set( query::u8${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type === 'smallint'){
				m = `${name} : Set( query::i16${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type === 'smallint unsigned'){
				m = `${name} : Set( query::u16${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type === 'bigint'){
				m = `${name} : Set( query::i64${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type === 'bigint unsigned'){
				m = `${name} : Set( query::u64${ not_null ? '' : '_op' }(&body, "${ name }")? )` 
			}else if( data_type.includes('decimal')){
				m = `${name} : Set( query::dec${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type === 'float'){
				m = `${name} : Set( query::f32${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type === 'double'){
				m = `${name} : Set( query::f64${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type.includes('json')){
				m = `${name} : Set( query::json${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type === 'date'){
				m = `${name} : Set( query::date${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type === 'date_time'){
				m = `${name} : Set( query::date_time${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type === 'timestamp'){
				m = `${name} : Set( query::date_time_utc${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}else if( data_type === 'time'){
				m = `${name} : Set( query::time${ not_null ? '' : '_op' }(&body, "${ name }")? )`
			}
			if(m) model_arr.push( tab +  m)
		}
	})
	
	column = column_arr.join(', ')
	model = model_arr.join(',\n') + ','
	
	return { column, model  }
}

export const getTemplateFileData = ({ cols, table_name, template }) => {
	const { column, model } = getBackData({ cols, is_tab:1 })
	template = template.replace(/%table_name%/g, table_name)
	template = template.replace(/%\*%/g, column)
	template = template.replace(/%#%/g, model)
	return template
}

export const getFrontData = ({ cols, is_tab }) => {
	let form_arr = []
	let table_arr = []
	let tab = is_tab ? '\t\t\t\t' : ''
	
	cols.forEach(({ Field, Type, Null, Comment })=>{
		//
		if( ![ 'id', 'uuid', 'create_user', 'update_user', 'create_time', 'update_time'].includes(Field) ){
			let type = null
			let r = Null === 'No' ? 1 : null
			if( Type.includes('int') || Type.includes('float') || Type.includes('double') || Type.includes('decimal')  ) type = { type: 'number' }
			if( Type.includes('bool') ) type = { type: 'radio' }
			if( Type.includes('date') || Type.includes('time') || Type.includes('year') ) type = { type: 'date' }
			
			let ellipsis
			let width = 100
			if( Field === 'mark '){
				type = { type: 'textarea' }
				ellipsis = 1
				width = null
			}
			
			form_arr.push({ label:Comment, name:Field, ...type, ...r })
			
			table_arr.push({ title:Comment, dataIndex: Field, ellipsis, width })
		}
	})
	// 表单
	form_arr = form_arr.map( v => {
		let stack = []
		for( let i in v){
			if(v[i] !== undefined && v[i] !== null){
				stack[i] = v[i]
			}
		}
		return stack
	})
	let form_str = ''
	form_arr.forEach( (v,t) => {
		let str = ''
		let k = 0
		for( let i in v){
			k ++
			str += `${i}: ` + ( typeof v[i] === 'string' ? `'${v[i]}'` : v[i] ) + ( k === Object.keys(v).length ? '' : ', ' )
		}
		form_str += tab + '{ ' + str + ' }' + ( t === form_arr.length -1 ? '' : ',\n' )
	})
	
	// 表格
	table_arr  = table_arr.map( v => {
		let stack = {}
		for( let i in v){
			if(v[i] !== undefined && v[i] !== null){
				stack[i] = v[i]
			}
		}
		return stack
	})
	
	let table_str = ''
	table_arr.forEach( (v,t) => {
		let str = ''
		let k = 0
		for( let i in v){
			k ++
			str += `${i}: ` + ( typeof v[i] === 'string' ? `'${v[i]}'` : v[i] ) + ( k === Object.keys(v).length ? '' : ', ' )
		}
		table_str += tab + '{ ' + str + ' }' + ( t === table_arr.length -1 ? '' : ',\n' )
	})
	
	return { form_str, table_str }
}

export const getFrontTemplateData = ({ cols, template }) => {
	const { form_str, table_str } = getFrontData({ cols, is_tab:1 })
	template = template.replace(/%\*%/g, table_str)
	template = template.replace(/%#%/g, form_str)
	return template
}

export default { getTemplateFileData, getFrontTemplateData }